#ifndef __BUFF__
#define __BUFF__
#include <vector>
#include <assert.h>
// extern std::ofstream ofs;


namespace Log
{
    /*
        异步日志器使用双缓冲，我们需要自定义缓冲区
    */

    /*
        异步日志器在非安全模式下进行扩容的策略：
            1.当buffer大小,未达到阈值之前,buffer的扩容方案是 2倍扩容
            2.当buffer大小,达到阈值后,buffer的扩容方案是 线性增长
    */

// 1.缓冲区的问题 不能给太大
#define DEFAULT_BUFFER_SIZE (1024 * 1024)  // 缓冲区默认大小
#define INCREASE_BUFFER_SIZE (1024 * 1024)     // 线性增长的大小
#define THRESHOLD_BUFFER_SIZE (1024* 1024 * 6) // 阈值

    // 生产缓冲区满了是否扩容？
    // 1. 扩容,是非安全模式下的操作,因为如果陷入死循环，
    //    然后扩容，会导致程序资源耗尽然后程序崩溃，常用于压力测试
    // 2. 不扩容，是安全模式，即使死循环了，我资源不会耗尽，程序仍然能跑，只不过有问题
    enum class AsyncType
    {
        ASYNC_SAFE,
        ASYNC_UNSAFE
    };

    // Buffer内部不涉及到锁的操作,锁操作统一在外面完成
    // 在生产者，消费者上面进行加锁操作
    class Buffer
    {
    private:
        // std::string _buf; // 缓冲区
        std::vector<char> _buf; // 缓冲区
        AsyncType _type; //异步日志器的模式
        size_t _index_con; // 消费者下标
        size_t _index_pro; // 生产者下标

    public:
        // void Printf_Con()
        // {
        //     ofs << "Buffer_消费者: ";
        //     string buf(_buf.begin()+_index_con,_buf.begin()+_index_pro);
        //     ofs << buf << std::endl;
        // }

        // void Printf_Pro()
        // {
        //     ofs << "Buffer_生产者: ";
        //     string buf(_buf.begin(),_buf.begin()+_index_con);
        //     ofs << buf << std::endl;
        // }

        Buffer(AsyncType type = AsyncType::ASYNC_UNSAFE)
        :_type(type),
        _buf(DEFAULT_BUFFER_SIZE),
        _index_con(0),
        _index_pro(0)
        {}
        // 判单缓冲区是否为空
        bool empty()
        {
            // return _buf.empty();
            // 同一个buf中如果读写指针指向同一个位置才表示空,没有数据
            // 读写指针指向不同的位置表示还有数据
            return _index_con == _index_pro;
        }

        // 交换
        void swap(Buffer& buf)
        {
            _buf.swap(buf._buf);
            // 对应的读写指针也需要交换!!! 
            std::swap(_index_con,buf._index_con);
            std::swap(_index_pro,buf._index_pro);
        }
        
        // 可读大小的空间
        size_t readable()
        {
            // return _buf.size() - _index_con;
            // 读写的数据!!!
            return _index_pro - _index_con;
        }

        // 可写大小空间
        size_t writeable()
        {
            return _buf.size() - _index_pro;
        }

        // 初始化缓冲区
        void reset()
        {
            _index_con = _index_pro = 0;
        }

        // 生产
        void push(const char* data,size_t len)
        {
            // 因为异步日志存在不同的模式
            // 我们需要在非安全模式下来才能进行扩容的处理
            if(_type == AsyncType::ASYNC_UNSAFE)
            {
                if(writeable() < len )
                    AddSpace(len);
            }
            assert(writeable() - len >= 0);
            std::copy(data, data + len, &_buf[_index_pro]);
            _index_pro += len;
         
        }
        

        // 获取可读的起始位置
        const char* readBegin()
        {
            return &_buf[_index_con];
        }        

        // 消费
        void pop(size_t len)
        {
            _index_con += len;
            assert(_index_con < _buf.size());
        }

    private:
        // 扩容
        bool AddSpace(size_t len)
        {
            // 要把len加上,免得扩容之后还是不够的情况
            size_t new_size = _buf.size() + len < THRESHOLD_BUFFER_SIZE ? \
                            _buf.size() * 2 + len : _buf.size() + len + INCREASE_BUFFER_SIZE;
            _buf.resize(new_size);
            // std::cout << "AddSpace successful" << std::endl;
        }

    };
}

#endif